package com.yuan.base.utils;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;

public class BitmapUtil {

	//-----------------------------------------整理后的新api------------------------------------------
	public static int computeSampleSize(int width, int height) {
		int MAX_IMAGE_DIMENSION = 1280;
		if (width > MAX_IMAGE_DIMENSION || height > MAX_IMAGE_DIMENSION) {
			float widthRatio = ((float) width) / MAX_IMAGE_DIMENSION;
			float heightRatio = ((float) height) / MAX_IMAGE_DIMENSION;
			float maxRatio = Math.max(widthRatio, heightRatio);
//			return (int) maxRatio;

			double log = Math.log(maxRatio) / Math.log(2);
			double logCeil = Math.ceil(log);
			return (int) Math.pow(2, logCeil);
		} else {
			return 1;
		}
	}

	public static BitmapFactory.Options calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
		// 获得内存中图片的宽高
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;
		if (height > reqHeight || width > reqWidth) {
			// 计算出一个数值，必须符合为2的幂（1，2，4，8，tec），赋值给inSampleSize
			// 图片宽高应大于期望的宽高的时候，才进行计算
			while ((height / inSampleSize) > reqHeight
					&& (width / inSampleSize) > reqWidth) {
				inSampleSize *= 2;
			}
		}
		// 设置压缩比例
		options.inSampleSize = inSampleSize;
		options.inJustDecodeBounds = false;
		return options;
	}

	/**
	 * 根据文件路径获取bitmap
	 */
	public static Bitmap getBitmapFromPath(String path) {
		Bitmap bitmap = null;
		try {
			File file = new File(path);
			if (!file.exists())
				return null;
			bitmap = BitmapFactory.decodeFile(path);
		} catch (OutOfMemoryError e) {
			e.printStackTrace();
		}
		return bitmap;
	}

	/**
	 * 获取一个指定大小的bitmap
	 * @param reqWidth  目标宽度(输出结果小于但不等于)
	 * @param reqHeight 目标高度(输出结果小于但不等于)
	 */
	public static Bitmap getBitmapFromPath(String path, int reqWidth, int reqHeight) {
		File file = new File(path);
		if (!file.exists())
			return null;
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);
		options = calculateInSampleSize(options, reqWidth, reqHeight);
		return BitmapFactory.decodeFile(path, options);
	}

	/**
	 * 获取一个指定大小的bitmap
	 * @param reqWidth  目标宽度(输出结果小于但不等于)
	 * @param reqHeight 目标高度(输出结果小于但不等于)
	 */
	public static Bitmap getBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
		// 第一次解析 inJustDecodeBounds=true 只是用来获取bitmap在内存中的尺寸和类型，系统并不会为其分配内存，
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeResource(res, resId, options);
		options = calculateInSampleSize(options, reqWidth, reqHeight);
		return BitmapFactory.decodeResource(res, resId, options);
	}

	/**
	 * 从View获取Bitmap
	 */
	public static Bitmap getBitmapFromView(View view) {
		Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmap);
		view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
		view.draw(canvas);
		return bitmap;
	}

	/**
	 * 压缩图片大小
	 * @param size 单位：kb
	 */
	public static Bitmap compressImage(Bitmap image, int size) {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		image.compress(Bitmap.CompressFormat.JPEG, 100, stream);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
		int options = 100;
		while (stream.toByteArray().length / 1024 > size) { // 循环判断如果压缩后图片是否大于size,大于继续压缩
			stream.reset();// 重置baos即清空baos
			image.compress(Bitmap.CompressFormat.JPEG, options, stream);// 这里压缩options%，把压缩后的数据存放到baos中
			options -= 10;// 每次都减少10
		}
		ByteArrayInputStream isBm = new ByteArrayInputStream(stream.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
		return BitmapFactory.decodeStream(isBm);
	}

	/**
	 * 获得圆角图片的方法
	 * @param bitmap  源Bitmap
	 * @param roundPx 圆角大小
	 */
	public static Bitmap getRoundCornerBitmap(Bitmap bitmap, float roundPx) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final int color = 0xff424242;
		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		final RectF rectF = new RectF(rect);

		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);
		bitmap.recycle();
		return output;
	}

	/**
	 * 转换图片成圆形
	 * @param bitmap 传入Bitmap对象
	 * @return 圆形Bitmap
	 */
	public static Bitmap getRoundBitmap(Bitmap bitmap) {
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		int radius = Math.min(width, height) >> 1;
		Bitmap output = Bitmap.createBitmap(width, height, bitmap.getConfig());
		Paint paint = new Paint();
		Canvas canvas = new Canvas(output);
		Rect rect = new Rect(0, 0, width, height);
		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		canvas.drawCircle(width >> 1, height >> 1, radius, paint);
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);

		bitmap.recycle();
		return output;
	}

	/**
	 * 旋转图片
	 * @param degree 旋转角度
	 * @param bitmap 需要旋转的图片的bitmap
	 * @return Bitmap 旋转后的图片bitmap
	 */
	public static Bitmap rotaingImageView(int degree, Bitmap bitmap) {
		if (degree == 0) {
			return bitmap;
		}
		// 旋转图片 动作
		Matrix matrix = new Matrix();
		matrix.postRotate(degree);
		// 创建新的图片
		Bitmap resizedBitmap = null;
		try {
			// 将原始图片按照旋转矩阵进行旋转，并得到新的图片
			resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
		} catch (OutOfMemoryError ignored) {
		}
		if (resizedBitmap == null) {
			return bitmap;
		}
		bitmap.recycle();
		return resizedBitmap;
	}
	//-----------------------------------------未整理api------------------------------------------

	/**
	 * 合并Bitmap
	 * @param bgd 背景Bitmap
	 * @param fg  前景Bitmap
	 * @return 合成后的Bitmap
	 */
	public static Bitmap combineImages(Bitmap bgd, Bitmap fg) {
		Bitmap bmp;

		int width = bgd.getWidth() > fg.getWidth() ? bgd.getWidth() : fg
				.getWidth();
		int height = bgd.getHeight() > fg.getHeight() ? bgd.getHeight() : fg
				.getHeight();

		bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
		Paint paint = new Paint();
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));

		Canvas canvas = new Canvas(bmp);
		canvas.drawBitmap(bgd, 0, 0, null);
		canvas.drawBitmap(fg, 0, 0, paint);

		return bmp;
	}

	/**
	 * 合并
	 * @param bgd 后景Bitmap
	 * @param fg  前景Bitmap
	 * @return 合成后Bitmap
	 */
	public static Bitmap combineImagesToSameSize(Bitmap bgd, Bitmap fg) {
		Bitmap bmp;

		int width = bgd.getWidth() < fg.getWidth() ? bgd.getWidth() : fg
				.getWidth();
		int height = bgd.getHeight() < fg.getHeight() ? bgd.getHeight() : fg
				.getHeight();

		if (fg.getWidth() != width && fg.getHeight() != height) {
			fg = zoom(fg, width, height);
		}
		if (bgd.getWidth() != width && bgd.getHeight() != height) {
			bgd = zoom(bgd, width, height);
		}

		bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
		Paint paint = new Paint();
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));

		Canvas canvas = new Canvas(bmp);
		canvas.drawBitmap(bgd, 0, 0, null);
		canvas.drawBitmap(fg, 0, 0, paint);

		return bmp;
	}

	/**
	 * 放大缩小图片
	 * @param bitmap 源Bitmap
	 * @param w      宽
	 * @param h      高
	 * @return 目标Bitmap
	 */
	public static Bitmap zoom(Bitmap bitmap, int w, int h) {
		if (bitmap == null) {
			return null;
		}
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		if (width <= w && height <= h) {
			return bitmap;
		}
		Matrix matrix = new Matrix();
		float scaleWidht = ((float) w / width);
		float scaleHeight = ((float) h / height);
		matrix.postScale(scaleWidht, scaleHeight);
		return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
	}

	/**
	 * Returns a Bitmap representing the thumbnail of the specified Bitmap. The
	 * size of the thumbnail is defined by the dimension
	 * android.R.dimen.launcher_application_icon_size.
	 * <p/>
	 * This method is not thread-safe and should be invoked on the UI thread
	 * only.
	 * @param bitmap  The bitmap to get a thumbnail of.
	 * @param context The application's context.
	 * @return A thumbnail for the specified bitmap or the bitmap itself if the
	 * thumbnail could not be created.
	 */
	public static Bitmap createThumbnailBitmap(Bitmap bitmap, Context context) {
		int sIconWidth = -1;
		int sIconHeight = -1;
		final Resources resources = context.getResources();
		sIconWidth = sIconHeight = (int) resources
				.getDimension(android.R.dimen.app_icon_size);

		final Paint sPaint = new Paint();
		final Rect sBounds = new Rect();
		final Rect sOldBounds = new Rect();
		Canvas sCanvas = new Canvas();

		int width = sIconWidth;
		int height = sIconHeight;

		sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
				Paint.FILTER_BITMAP_FLAG));

		final int bitmapWidth = bitmap.getWidth();
		final int bitmapHeight = bitmap.getHeight();

		if (width > 0 && height > 0) {
			if (width < bitmapWidth || height < bitmapHeight) {
				final float ratio = (float) bitmapWidth / bitmapHeight;

				if (bitmapWidth > bitmapHeight) {
					height = (int) (width / ratio);
				} else if (bitmapHeight > bitmapWidth) {
					width = (int) (height * ratio);
				}

				final Bitmap.Config c = (width == sIconWidth && height == sIconHeight) ? bitmap
						.getConfig() : Bitmap.Config.ARGB_8888;
				final Bitmap thumb = Bitmap.createBitmap(sIconWidth,
						sIconHeight, c);
				final Canvas canvas = sCanvas;
				final Paint paint = sPaint;
				canvas.setBitmap(thumb);
				paint.setDither(false);
				paint.setFilterBitmap(true);
				sBounds.set((sIconWidth - width) / 2,
						(sIconHeight - height) / 2, width, height);
				sOldBounds.set(0, 0, bitmapWidth, bitmapHeight);
				canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);
				return thumb;
			} else if (bitmapWidth < width || bitmapHeight < height) {
				final Bitmap.Config c = Bitmap.Config.ARGB_8888;
				final Bitmap thumb = Bitmap.createBitmap(sIconWidth,
						sIconHeight, c);
				final Canvas canvas = sCanvas;
				final Paint paint = sPaint;
				canvas.setBitmap(thumb);
				paint.setDither(false);
				paint.setFilterBitmap(true);
				canvas.drawBitmap(bitmap, (sIconWidth - bitmapWidth) / 2,
						(sIconHeight - bitmapHeight) / 2, paint);
				return thumb;
			}
		}

		return bitmap;
	}

	/**
	 * 生成水印图片 水印在右下角
	 * @param src       the bitmap object you want proecss
	 * @param watermark the water mark above the src
	 * @return return a bitmap object ,if paramter's length is 0,return null
	 */
	public static Bitmap createWatermarkBitmap(Bitmap src, Bitmap watermark) {
		if (src == null) {
			return null;
		}

		int w = src.getWidth();
		int h = src.getHeight();
		int ww = watermark.getWidth();
		int wh = watermark.getHeight();
		// create the new blank bitmap
		Bitmap newb = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
		Canvas cv = new Canvas(newb);
		// draw src into
		cv.drawBitmap(src, 0, 0, null);// 在 0，0坐标开始画入src
		// draw watermark into
		cv.drawBitmap(watermark, w - ww + 5, h - wh + 5, null);// 在src的右下角画入水印
		// save all clip
		cv.save();// 保存
		// store
		cv.restore();// 存储
		return newb;
	}

	/**
	 * 重新编码Bitmap
	 * @param src     需要重新编码的Bitmap
	 * @param format  编码后的格式（目前只支持png和jpeg这两种格式）
	 * @param quality 重新生成后的bitmap的质量
	 * @return 返回重新生成后的bitmap
	 */
	public static Bitmap codec(Bitmap src, Bitmap.CompressFormat format,
							   int quality) {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		src.compress(format, quality, os);

		byte[] array = os.toByteArray();
		return BitmapFactory.decodeByteArray(array, 0, array.length);
	}

	/**
	 * 图片压缩方法：（使用compress的方法）
	 * <p/>
	 * <br>
	 * <b>说明</b> 如果bitmap本身的大小小于maxSize，则不作处理
	 * @param bitmap  要压缩的图片
	 * @param maxSize 压缩后的大小，单位kb
	 */
	public static void compress(Bitmap bitmap, double maxSize) {
		// 将bitmap放至数组中，意在获得bitmap的大小（与实际读取的原文件要大）
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		// 格式、质量、输出流
		bitmap.compress(Bitmap.CompressFormat.PNG, 70, baos);
		byte[] b = baos.toByteArray();
		// 将字节换成KB
		double mid = b.length / 1024;
		// 获取bitmap大小 是允许最大大小的多少倍
		double i = mid / maxSize;
		// 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩
		if (i > 1) {
			// 缩放图片 此处用到平方根 将宽带和高度压缩掉对应的平方根倍
			// （保持宽高不变，缩放后也达到了最大占用空间的大小）
			bitmap = scale(bitmap, bitmap.getWidth() / Math.sqrt(i),
					bitmap.getHeight() / Math.sqrt(i));
		}
	}

	/**
	 * 图片的缩放方法
	 * @param src       ：源图片资源
	 * @param newWidth  ：缩放后宽度
	 * @param newHeight ：缩放后高度
	 */
	public static Bitmap scale(Bitmap src, double newWidth, double newHeight) {
		// 记录src的宽高
		float width = src.getWidth();
		float height = src.getHeight();
		// 创建一个matrix容器
		Matrix matrix = new Matrix();
		// 计算缩放比例
		float scaleWidth = ((float) newWidth) / width;
		float scaleHeight = ((float) newHeight) / height;
		// 开始缩放
		matrix.postScale(scaleWidth, scaleHeight);
		// 创建缩放后的图片
		return Bitmap.createBitmap(src, 0, 0, (int) width, (int) height,
				matrix, true);
	}

	/**
	 * 图片的缩放方法
	 * @param src         ：源图片资源
	 * @param scaleMatrix ：缩放规则
	 */
	public static Bitmap scale(Bitmap src, Matrix scaleMatrix) {
		return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(),
				scaleMatrix, true);
	}

	/**
	 * 图片的缩放方法
	 * @param src    ：源图片资源
	 * @param scaleX ：横向缩放比例
	 * @param scaleY ：纵向缩放比例
	 */
	public static Bitmap scale(Bitmap src, float scaleX, float scaleY) {
		Matrix matrix = new Matrix();
		matrix.postScale(scaleX, scaleY);
		return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(),
				matrix, true);
	}

	/**
	 * 图片的缩放方法
	 * @param src   ：源图片资源
	 * @param scale ：缩放比例
	 */
	public static Bitmap scale(Bitmap src, float scale) {
		return scale(src, scale, scale);
	}



}
